# -*- coding: utf-8 -*-

from django.db import models, transaction
from core.models import CoreModel, table_prefix
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from apps.sys.dict.models import DictData

"""测试主机对象"""


class Host(CoreModel):
    TYPE_CHOICES = (
        (0, "密码验证"),
        (1, "私钥验证"),
    )
    name = models.CharField(max_length=128, verbose_name="主机名称")
    number = models.CharField(
        null=True, blank=True, max_length=128, verbose_name="主机型号"
    )
    address = models.CharField(unique=True, max_length=32, verbose_name="主机地址")
    port = models.IntegerField(default=22, verbose_name="端口号")
    username = models.CharField(
        null=True, blank=True, max_length=128, verbose_name="用户名"
    )
    password = models.CharField(
        null=True, blank=True, max_length=128, verbose_name="密码"
    )
    os = models.CharField(max_length=200, verbose_name="操作系统")
    enable = models.CharField(default="0", max_length=50, verbose_name="是否启用")
    type = models.CharField(max_length=50, default="0", verbose_name="主机类型")
    pkey = models.CharField(null=True, blank=True, max_length=255, verbose_name="私钥")
    pkey_passwd = models.CharField(
        null=True,
        blank=True,
        max_length=255,
        verbose_name="私钥密码",
    )
    vtype = models.SmallIntegerField(
        default=0, choices=TYPE_CHOICES, verbose_name="验证方式"
    )

    def __str__(self) -> str:
        return "%s(%s)" % (self.name, self.address)

    class Meta:
        db_table = table_prefix + "oms_host"
        verbose_name = "主机管理"
        verbose_name_plural = verbose_name
        ordering = ("-update_time",)


class HostManager:
    # 更新状态
    @staticmethod
    def set_host_status(host_id, new_status):
        """Set the status of a host and save the changes to the database."""
        try:
            with transaction.atomic():
                host = Host.objects.select_for_update().get(id=host_id)
                if host.status == new_status:
                    new_status_label = DictData.objects.get(
                        type="oms_host_status", value=new_status
                    ).label
                    raise ValidationError(
                        f"The host is already in the desired state: {new_status_label}"
                    )
                host.status = new_status
                host.save()
                return host
        except Host.DoesNotExist:
            raise ValueError(f"No host found with ID: {host_id}")

    # 申请主机
    @staticmethod
    def achieve_host(filters=None):
        filters = filters or {}
        # 添加基本的筛选条件：状态为空闲
        filters["status"] = "0"

        try:
            with transaction.atomic():
                host = Host.objects.select_for_update().filter(**filters).first()
                if not host:
                    raise ValueError("No available hosts that match the queryset.")
                return HostManager.set_host_status(host.id, "1")
        except Host.DoesNotExist:
            raise ValueError("Failed to fetch any hosts for allocation.")

    # 释放主机
    @staticmethod
    def release_host(host_id):
        """Release a host by setting its status to 'free', if applicable."""
        try:
            host = Host.objects.get(id=host_id)
            # status 为 "2" 表示主机故障
            if host.status == "2":
                raise ValueError("The host is in a fault state and cannot be released.")
            return HostManager.set_host_status(host_id, "0")
        except ObjectDoesNotExist:
            raise ValueError(f"Host with ID {host_id} does not exist.")
